import * as THREE from 'three';
import { CSS2DObject, CSS2DRenderer } from '../assert/js/CSS2DRenderer'
import { OrbitControls } from 'three/examples/jsm/controls/OrbitControls'
import ColladaLoader from '../assert/js/ColladaLoader'

import './show'
import dataShow from './data_show'
import { Mesh } from 'three';



const debug = false
const scene = new THREE.Scene();
/**
 * 创建网格模型
 */
// 辅助坐标系 
// if (debug) {
//   var axes = new THREE.AxesHelper(1000);
//   scene.add(axes);
// }

const loader = new ColladaLoader();

let qs = {}
    ; (() => {
        const query = window.location.search.substring(1);
        let res = {}
        const vars = query.split("&");
        for (let i = 0; i < vars.length; i++) {
            var pair = vars[i].split("=");
            res[pair[0]] = pair[1]
        }
        qs = res
    })()
let fillStyleMap = {
    '自持': '#cccccc',
    '公寓': '#cccccc',
    '公租': '#cccccc',
    '物业': '#cccccc',
    '商业': '#cccccc',
    '办公': '#cccccc',
    '已开': '#cccccc',
    '未开': '#bcdabe',
    '预计': '#4da5ff',
    '本期': '#fdab71'

}

let groupArr
let dy, dx
let fov = 50, near = 1, fear = 3000, json
let mesh = null
let loadUrl, colorUrl
let ambLight, light, plane
// 颜色常量
let color1 = new THREE.Color(0xffb3a7);
let color2 = new THREE.Color(0xf3d0a8);
let color3 = new THREE.Color(0xf3eaa7);
let color4 = new THREE.Color(0xcbe47c);
let color5 = new THREE.Color(0xa1d97b);

let color
let colors = [];
let normals;
let buildUnitMap;
let numStrArr
let animHandler


//设置建筑名称
$('.build_name').html(decodeURI(qs.building.trim()))
const getDaeUrl = (dae, prefix) => `https://${prefix}/dae/${dae}.dae`
let splits = qs.dae.trim().split(',')
let prefix = qs.prefix.trim()
if (splits.length === 1) {
    //只有一个楼栋
    loadUrl = getDaeUrl(splits[0], prefix)
} else {
    loadUrl = splits.map(function (s) {
        const [t, u] = s.split('-')
        return {
            t: decodeURI(t),
            u: getDaeUrl(u, prefix)
        }
    }
    )
}


if (debug) {
    loadUrl = [
        { t: '南区', u: `/dae/7.dae` },
        { t: '北区', u: `/dae/7.dae` }
    ]
    loadUrl = `/dae/噪声没路的模型.dae`
    colorUrl = `/json/噪声没路的模型.json`
} else {
    console.log = () => { }
    colorUrl = `${qs.url.trim()}?code=${qs.code.trim()}`
}

//根据模型数，显示ui
const $daes = $('#daes')
if (loadUrl instanceof Array) {
    $daes.show()
    loadUrl.forEach(({ t }) => {
        $daes.append(`<span>${t}</span>`)
    })

} else {

    $daes.hide()
}
function sceneryToColor(v) {
    if (v < 60) {
        return color1
    } else if (v < 70) {
        return color2
    } else if (v < 80) {
        return color3
    } else if (v < 90) {
        return color4
    } else {
        return color5
    }
}
function correctArr(numStrArr) { //修改处5，新增方法，对特殊数组处理
    if (numStrArr.length == 5) { //数组有5个元素时前两个数字代表楼号
        numStrArr[0] = numStrArr[0] + "-" + numStrArr[1]
        numStrArr[1] = numStrArr[2]
        numStrArr[2] = numStrArr[3]
        numStrArr[3] = numStrArr[4]
    }
    return numStrArr
}

function setSceneryColor() {
    let vertexMaterial = new THREE.MeshStandardMaterial({
        side: THREE.DoubleSide, //两个三角面均可见
        vertexColors: true,
    }); //材质对象
    for (let a = 0; a < groupArr.length; a++) {
        if (groupArr[a].name.search("-") != -1) { //筛选出name包含"-"的元素
            numStrArr = correctArr(groupArr[a].name.replace("_", "").split("-")) //修改处2，所有出现groupArr[a].name.replace("_","").split("-")的地方加上一个correctArr方法处理

            try {
                normals = groupArr[a].children[0].geometry.attributes.normal.array //每个顶点所在面的法向量数组，每3个数字表示一个顶点
                colors = new Array(normals.length); //颜色数组数量需要和顶点个数保持一致，每3个数字表示一个颜色
                colors.fill(0.6) //楼面默认填充灰色
                let arr = json.data.find(item => item.name === numStrArr[0] + "#").data.reduce(function (a, b) { return a.concat(b) }); //二维数组变一维数组
                let houseData = arr[buildUnitMap.get(numStrArr[0]).indexOf(numStrArr[1] + "-" + numStrArr[2])][parseInt(numStrArr[3]) - 1] //先通过楼号从hash表中拿到数组，name中间两个数字在数组的索引就代表第几列
                if (houseData != null) {
                    if (houseData.allScore != undefined) {
                        color = sceneryToColor(houseData.allScore)
                    }
                    for (let i = 0; i < normals.length; i += 3) {
                        colors[i] = color.r
                        colors[i + 1] = color.g
                        colors[i + 2] = color.b
                    }
                    groupArr[a].children[0].geometry.attributes.color = new THREE.Float32BufferAttribute(colors, 3);
                    // 三角面(网格)渲染模式
                    groupArr[a].children[0].material = vertexMaterial
                }
            } catch (error) {
                continue
            }

        }
        renderer.info.reset()
    }


}

function loadDae(url) {
    //加载动画
    $('#loading_mask').show()
    //移除渲染
    window.cancelAnimationFrame(animHandler)
    animHandler = -1
    //移除之前的模型
    if (mesh) {
        console.log(mesh)
        scene.clear()
        reset()

    }
    scene.add(light)
    scene.add(ambLight)
    scene.add(plane)

    // 添加模型
    loader.load(url, result => {

        mesh = result.scene
        let box = new THREE.Box3().setFromObject(mesh);  // 定位  
        mesh.rotation.x = - 0 / 180 * Math.PI //x轴对齐
        mesh.rotation.y = - 0 / 180 * Math.PI
        mesh.rotation.z = 90 / 180 * Math.PI
        let mdwid = box.max.x - box.min.x;
        let mdHei = box.max.z - box.min.z;
        dy = mdwid / 2 + box.min.x
        dx = mdHei / 2 + box.min.z

        mesh.position.set(-dx, -dy)
        mesh.receiveShadow = true
        // mesh.material.depthTest = false
        mesh.children[0].receiveShadow = true
        //显示道路阴影
        for (let item of mesh.children[0].children) {
            // console.log(item)
            if (item.name && item.name.indexOf('-') == -1 && item.name.indexOf("instance") == -1) {
                item.children.forEach(ii => {

                    if (ii instanceof Mesh) {

                        ii.geometry.computeBoundingSphere()
                        const { z } = ii.geometry.boundingSphere.center
                        if (z) return
                        ii.castShadow = true
                        ii.receiveShadow = true
                        ii.material.opacity = 1
                        ii.material.transparent = false

                        // let colorMaterial = new THREE.MeshStandardMaterial({
                        //     side: THREE.BackSide, //两个三角面均可见
                        // }); //材质对象
                        // let color = new THREE.Color(0x666666)
                        // ii.material = colorMaterial
                        // ii.material.color = color
                        // ii.material.depthWrite = true
                    }

                })


            } else {

                // console.log(item.name)
            }

        }
        groupArr = result.scene.children[0].children

        var buildTopFloors = new Map //楼号-最高层数的散列表
        for (var a = 0; a < groupArr.length; a++) {
            if (groupArr[a].name.search("-") != -1) {
                numStrArr = correctArr(groupArr[a].name.replace("_", "").split("-")) //修改处2，所有出现groupArr[a].name.replace("_","").split("-")的地方加上一个correctArr方法处理

                if (buildTopFloors.get(numStrArr[0]) == null) {
                    buildTopFloors.set(numStrArr[0], numStrArr[3])
                } else {
                    if (parseInt(numStrArr[3]) > parseInt(buildTopFloors.get(numStrArr[0]))) {
                        buildTopFloors.set(numStrArr[0], numStrArr[3])
                    }
                }
            }
        }
        buildUnitMap = new Map()
        buildTopFloors.forEach(function (value, key) {
            buildUnitMap.set(key, [])
        })
        for (var a = 0; a < groupArr.length; a++) {
            if (groupArr[a].name.search("-") != -1) {
                numStrArr = correctArr(groupArr[a].name.replace("_", "").split("-")) //修改处2，所有出现groupArr[a].name.replace("_","").split("-")的地方加上一个correctArr方法处理

                if (numStrArr[3] == "1") {
                    if (buildUnitMap.get(numStrArr[0]).indexOf(numStrArr[1] + "-" + numStrArr[2]) == -1) {
                        buildUnitMap.get(numStrArr[0]).push(numStrArr[1] + "-" + numStrArr[2])
                    }
                }
            }
        }
        let promise
        console.log("colorUrl", colorUrl, json)
        if (!json) {
            promise = fetch(colorUrl)
        } else {
            promise = new Promise((r) => r(json))
        }

        promise.then(async res => {
            if (!json) {
                json = await res.json()
            }
            setSceneryColor()
            buildNoPositionMap.forEach((value, key) => {
                console.log(json)
                let target = json.data.find(item => item.name === key + "#")
                console.log("target", target)
                addBuildingTag(key, value[0], value[1], value[2], target.status, target.floor)
            })

            $('#loading_mask').hide()
            dataShow()

        }).catch(() => {
            $('#loading_mask').hide()
            dataShow()


        })
        let boxInnerCenter, h, topCenter
        var buildTopFloors = new Map //楼号-最高层数的散列表
        for (let a = 0; a < groupArr.length; a++) {
            if (groupArr[a].name.search("-") != -1) {
                numStrArr = correctArr(groupArr[a].name.replace("_", "").split("-")) //修改处2，所有出现groupArr[a].name.replace("_","").split("-")的地方加上一个correctArr方法处理

                if (buildTopFloors.get(numStrArr[0]) == null) {
                    buildTopFloors.set(numStrArr[0], numStrArr[3])
                } else {
                    if (parseInt(numStrArr[3]) > parseInt(buildTopFloors.get(numStrArr[0]))) {
                        buildTopFloors.set(numStrArr[0], numStrArr[3])
                    }
                }
            }
        }

        var peakArrMap = new Map() //楼号-顶楼各群组中心点数组的散列表
        buildTopFloors.forEach(function (value, key) {
            peakArrMap.set(key, [])
        })
        for (let a = 0; a < groupArr.length; a++) {

            if (groupArr[a].name.search("-") != -1) {
                numStrArr = correctArr(groupArr[a].name.replace("_", "").split("-")) //修改处2，所有出现groupArr[a].name.replace("_","").split("-")的地方加上一个correctArr方法处理

                if (numStrArr[3] == buildTopFloors.get(numStrArr[0])) { //最高层的某个群组
                    groupArr[a].children[0].geometry.computeBoundingSphere()
                    boxInnerCenter = groupArr[a].children[0].geometry.boundingSphere.center
                    peakArrMap.get(numStrArr[0]).push({
                        x: groupArr[a].position.x + boxInnerCenter.x,
                        y: groupArr[a].position.y + boxInnerCenter.y,
                        z: groupArr[a].position.z + boxInnerCenter.z
                    })
                }
            }
        }

        var buildNoPositionMap = new Map() //楼号-楼号标签位置的散列表

        peakArrMap.forEach(function (value, key) {
            console.log(value)
            var x = 0, y = 0
            var peakArr = value
            for (h = 0; h < peakArr.length; h++) {
                x += peakArr[h].x;
                y += peakArr[h].y;
            }
            topCenter = [x / peakArr.length / 39.4, y / peakArr.length / 39.4, peakArr[0].z / 39.4]
            buildNoPositionMap.set(key, topCenter)
        })


        scene.add(mesh)
        render()

    })

}


// 添加底板
let planeGeometry = new THREE.PlaneGeometry(3000, 3000);
let planeMaterial = new THREE.MeshStandardMaterial({ color: 0xcccccc });
// 关闭deptchTest，使该材质无视渲染顺序，必定被渲染（防止重叠闪烁）
planeMaterial.depthTest = false
// planeMaterial.depthWrite = true
plane = new THREE.Mesh(planeGeometry, planeMaterial);
//设置平面需要接收阴影
plane.receiveShadow = true;
scene.add(plane);



/**
 * 光源设置
 */
// 第二个参数为光照强度，2倍
light = new THREE.DirectionalLight(0xFFFAF0, 0.1)

light.position.set(0, 0, 600); //点光源位置
light.castShadow = true;//开启阴影
light.shadow.mapSize.width = 4096; //阴影贴图宽度设置为2048像素
light.shadow.mapSize.height = 4096; //阴影贴图高度设置为2048像素
light.shadow.radius = 0;
//Set up shadow properties for the light
light.shadow.camera.near = 100;
light.shadow.camera.far = 3000;
light.shadow.camera.left = -300;
light.shadow.camera.right = 300;
light.shadow.camera.top = 300;
light.shadow.camera.bottom = -300;
light.shadow.color = '#ff0000'
// const light = new THREE.PointLight(0xFFFFFF);
light.position.set(0, 0, 600); //点光源位置
// scene.add(light);
// //环境光 由于环境光作用于所有的物体，所有的材质，所以环境光是没有方向的，也无法产生阴影效果。
ambLight = new THREE.AmbientLight(0xffffff, 0.9)
scene.add(ambLight);

// if (debug) {
//   const helper = new THREE.CameraHelper(light.shadow.camera);
//   scene.add(helper);
// }



/**
 * 相机设置
 */
let width = window.innerWidth; //窗口宽度
let height = window.innerHeight - $('#date-controller').height(); //窗口高度
var k = width / height; //窗口宽高比
var s = 300; //三维场景显示范围控制系数，系数越大，显示的范围越大
//创建相机对象
const camera = new THREE.PerspectiveCamera(fov, width / height, near, fear);
camera.position.set(400, 0, 500); //设置相机位置
camera.up.x = 0;
camera.up.y = 0;
camera.up.z = 1; //z轴向上
camera.lookAt(scene.position); //设置相机方向(指向的场景对象)

/**
 * 创建渲染器对象
 */
const renderer = new THREE.WebGLRenderer({
    antialias: true, // true/false表示是否开启反锯齿
    alpha: true, // true/false 表示是否可以设置背景色透明
    logarithmicDepthBuffer: true,
    checkShaderErrors: false, //关闭检查提高性能
});
renderer.shadowMap.enabled = true
renderer.shadowMap.needsUpdate = true
renderer.shadowMap.type = THREE.PCFSoftShadowMap
renderer.setSize(width, height);//设置渲染区域尺寸
renderer.setClearColor(0xb9d3ff, 1); //设置背景颜色
renderer.setScissorTest(false)
renderer.info.autoReset = false
renderer.setPixelRatio(window.devicePixelRatio);//设置canvas的像素比为当前设备的屏幕像素比，避免高分屏下模糊
renderer.physicallyCorrectLights = false
document.getElementById('app').appendChild(renderer.domElement); //body元素中插入canvas对象


const controls = new OrbitControls(camera, renderer.domElement);//创建控件对象
//设置相机角度
//上下翻转的最大角度
controls.maxPolarAngle = 1.4;
//上下翻转的最小角度
controls.minPolarAngle = 0;
//是否允许缩放
controls.enableZoom = true;

controls.enableDamping = true
controls.maxZoom = 10
controls.minZoom = 0.8

//添加标签
//初始化CSS2渲染器
const labelRenderer = new CSS2DRenderer();
labelRenderer.setSize(width, height);
labelRenderer.domElement.style.position = 'absolute';
labelRenderer.domElement.style.pointerEvents = 'none'
labelRenderer.domElement.style.boxSizing = 'border-box'
labelRenderer.domElement.style.top = 0;

document.body.appendChild(labelRenderer.domElement);


//render
function render() {

    controls.update()

    renderer.render(scene, camera);//执行渲染操作
    labelRenderer.render(scene, camera)

    //指南针

    //只考虑xoy平面，本项目x轴为南，y轴为东，即x轴负方向为正北方向
    //取与相机相反方向的向量，即目光所在的向量
    let dir = new THREE.Vector3(-camera.position.x, -camera.position.y, 0).normalize();

    let theta = Math.atan2(-dir.y, -dir.x);

    //指南针旋转
    $('#guide-wrap .compass').css({ 'transform': 'translate(-50%, -50%) rotate(' + THREE.Math.radToDeg(theta) + 'deg)' });
    animHandler = requestAnimationFrame(render);
}

function reset() {
    camera.position.set(400, 0, 500)
    controls.reset()
}



//添加标签文字材质
function addBuildingTag(text, x, y, z, status, lou) {
    let tagDiv = document.createElement('div')//创建div容器

    tagDiv.className = 'building_tag'
    tagDiv.innerHTML = `<span style="font-size: 12px;">${text}</span>#`
    if (status) {
        tagDiv.innerHTML += `${status}`
    }
    if (lou) {
        tagDiv.innerHTML += `&nbsp;<span style="font-size: 12px;">${lou}</span>F`
    }
    tagDiv.style.pointerEvents = 'all';
    tagDiv.style.color = '#111'
    tagDiv.style.boxSizing = 'border-box'

    tagDiv.style.fontSize = '10px'
    tagDiv.style.borderRadius = '7px'
    tagDiv.style.lineHeight = '14px'
    tagDiv.style.paddingLeft = '2px'
    tagDiv.style.paddingRight = '2px'
    tagDiv.style.border = '1px solid #111'

    tagDiv.style.verticalAlign = 'baseline'
    tagDiv.style.backgroundColor = fillStyleMap[status] + 'ee'
    if (!status) {
        tagDiv.style.backgroundColor = '#FFFFFFEE'
    }
    tagDiv.addEventListener('click', () => {
        // controls.reset()
        let _x = -y - dx
        let _y = x - dy
        let _z = z + 20
        let d = Math.sqrt(_x * _x + _y * _y)
        let r = Math.sqrt(d * d + _z * _z)


        let dis = 200

        let newD = (r + dis) / r * d


        let newX = newD / d * _x
        let newY = newD / d * _y

        let newZ = Math.sqrt(newD * newD + (r + dis) * (r + dis))

        console.log(_x, _y, _z, r, '    ', newX, newY, 0)

        camera.position.set(newX, newY, _z + 10)

    })

    let pointLabel = new CSS2DObject(tagDiv);
    pointLabel.position.set(-y - dx, x - dy, z + 20);
    // pointLabel.position.set(y - this.dx, x - this.dy, z + 10);
    // pointLabel.rotation.z = 90 / 180 * Math.PI
    scene.add(pointLabel)

}


//请求数据

if (loadUrl instanceof Array) {

    loadDae(loadUrl[0].u)
} else {
    loadDae(loadUrl)
}

//------------------模型切换----------------------


$('#daes span').on('click', function () {
    $(this).attr('class', 'select')
    $($('#daes span')[($(this).index() + 1) % 2]).attr('class', '')


    //切换显示
    loadDae(loadUrl[$(this).index()].u)
    //重置到白天
})
//默认选中第一个
$($('#daes span')[0]).attr('class', 'select')
//--------------------end-----------------

//重置按钮
$('#btn_reset').on('click', () => {
    //默认选中第一个
    reset()
})

